package aima.search;

import java.lang.*;
import java.util.*;
import aima.cs.util.*;

/** 
   Search node represents a node in a search tree and supplies
   utility functions needed for implementing a search.
*/

public class SearchNode {

/** State at this node */
   protected State state;
/** Reference back to parent node. */
   protected SearchNode parent;
/** Operation that was applied to parent */
   protected String appliedOp;
/** Depth of this node */
   protected int depth;
/** Cost of getting to this node */
   protected float pathCost;

/** No-argument constructor needed for newInstance() */ 
   protected SearchNode() { }

/** Constructor takes a state and makes it a parentless search node */
   public SearchNode(State startState) {
      state = startState;
      parent = null;
      appliedOp = null;
      depth = 0;
      pathCost = 0;
   }

/** Returns state of this node. */
   public State getState() {
         return state;
   } 

/** Returns parent of this node. */
   public SearchNode getParent() {
         return parent;
   }

/** Returns applied operation for this node. */
   public String getAppliedOp() {
         return appliedOp;
   }

/** Returns depth of this node. */
   public int getDepth() {
         return depth;
   }

/** Returns cost of getting to this node */
   public float getPathCost() {
        return pathCost; 
   }

/** Expands a node into its successors */
   public void expand(GeneralQueue expandInto) {

      Enumeration successorList = getState().successors();
      while (successorList.hasMoreElements()) {
          expandInto.add(makeNode( (Successor)successorList.nextElement()) );
      }

   }

/** Makes a new node of the same type as this one, using a 
    successor returned by an object of type State */
   public SearchNode makeNode(Successor successor) {
        SearchNode newNode;

        try {
          newNode = (SearchNode) getClass().newInstance();

          newNode.state = successor.getState();
          newNode.parent = this;
          newNode.appliedOp = successor.getOperatorName();
          newNode.depth = depth+1; 
          newNode.pathCost = pathCost + successor.getCost();

          return newNode;
        } catch (InstantiationException e) {
        } catch (IllegalAccessException e) {
        }

        return null; 
  } 
}
